package com.qf.cx.simplenms.link.impl;

import com.qf.cx.simplenms.link.api.Link;
import com.qf.cx.simplenms.link.api.LinkManager;
import com.qf.cx.simplenms.link.api.LinkStatus;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by linda on 2016/11/13.
 */
@Component
public class LogicLinkManagerImpl implements LinkManager, LinkStatus {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private PhysicalLinkMaintainerIF physicalLinkMaintainerIF;
	private Map<String, Link> links = new ConcurrentHashMap<>();
	private Set<ReaderSource> rs = new HashSet<ReaderSource>();

	public PhysicalLinkMaintainerIF getPhysicalLinkMaintainerIF() {
		return physicalLinkMaintainerIF;
	}

	public void setPhysicalLinkMaintainerIF(PhysicalLinkMaintainerIF physicalLinkMaintainerIF) {
		this.physicalLinkMaintainerIF = physicalLinkMaintainerIF;
	}

	@Override
	public boolean startListen(int port) {
		logger.info("link mannger start listen port:{}", port);
		try {
			physicalLinkMaintainerIF.listen("", port);
		} catch (Exception e) {
			logger.error("", e);
		}
		return true;
	}

	@Override
	public synchronized Link establish(ReaderSource readerSource) {
		final String readerIdentifier = readerSource.getReaderIdentifier();
		final Link link = links.get(readerIdentifier);
		if (null != link) {
			return link;
		}
		logger.info("a reader:{},add into the link mannger", readerSource);
		final ReaderLink newLink = new ReaderLink(readerSource, physicalLinkMaintainerIF);
		links.put(readerIdentifier, newLink);
		rs.add(readerSource);
		return newLink;
	}

	@Override
	public synchronized void close(ReaderSource readerSource) {
		final String readerIdentifier = readerSource.getReaderIdentifier();
		final Link link = links.get(readerIdentifier);
		if (link == null) {
			return;
		}
		logger.info("a reader:{},remove from the link mannger", readerSource);
		link.stop();
		links.remove(readerIdentifier);
		rs.remove(readerSource);
	}

	@Override
	public synchronized Map<String, State> getLinkStatus() {

		final Map<String, State> readersState = new HashMap<String, State>();

		for (ReaderSource r : rs) {
			PhysicalLinkIF phylink = physicalLinkMaintainerIF.getLink(r);
			if (phylink.isOk()) {
				readersState.put(r.getReaderIdentifier(), State.UP);
			} else {
				readersState.put(r.getReaderIdentifier(), State.DOWN);
			}
		}

		for (Entry<String, State> info : readersState.entrySet()) {
			logger.debug("reader link status:{}", info);
		}
		return readersState;
	}
}
